if (! this.EventBroadcaster) load("EventBroadcaster.asc");

// Base class for the server-side communication component.
try { var dummy = RTCFComponent; } catch ( e ) {

function RTCFComponent(id, classPath, resourcePath){

	// The RTCFComponent class itself should be treated as an abstract class which is
	// never instantiated. However, this constructor function will be called because
	// it is used to overwrite RTCFComponent subclass prototype objects. When that happens
	// this function will be called without parameters and will just return.
	// This function is also called by the framework when a component is created.
	// In that case parameters should be passed in.
	
	if (arguments.length == 0){
		return;
	}
	
	
	// Save the parameters:
	this._rmiID_ = id;
	this._classPath_ = classPath;
	this._resourcePath_ = resourcePath;
	this._fullResourcePath_ = "rtcfResources/" + resourcePath;
	this._filePath_ = "rtcfFiles/" + application.name.substring(application.name.indexOf("/")+1) + "/" + resourcePath;
	this._writeAccessPaths_ = {};
	this._readAccessPaths_ = {};
	
	// By default components are visible to the client. Null this out to hide the component. Add roles to restrict to certain clients by role.
	this._roles_ = {}; 
	
	// The framework will set a reference to itself here: this.rtcf
}

p = RTCFComponent.prototype;

p.init = function(){
	// do Nothing. Subclasses should implement this method to
	// in order to setup listeners on the application object
	// if necessary. 
	// For example application.rtcf.addListener("onAuthorizedConnect", this);
	trace("WARNING! This method should not be called: RTCFComponent.init> ");
}

p.hasRoles = function(){
	if (! this._roles_) return false;
	for (var p in this._roles_){
		return true;
	}
	return false;
}

p.allowRemoteCall = function(methodName){
	remoteMethod = this[methodName];
	if (! remoteMethod){
		trace("ERROR! RTCFComponent.allowRemoteCall. Method not defined: " + methodName );
		return null;	
	}
	if (typeof remoteMethod != "function"){
		trace("ERROR! RTCFComponent.allowRemoteCall. Method not a function: " + methodName );
		return null;	
	}
	if (arguments.length < 3){
		trace("Warning! RTCFComponent.allowRemoteCall. : " + methodName + " is a public method and can be called by any client regardless of role." );	
	}

	if (! remoteMethod.roles) remoteMethod.roles = [];
	for (var i = 1; i < arguments.length; i++){
		remoteMethod.roles.push(arguments[i]);
	}
	// trace("Roles have been set on " + methodName + ": " + remoteMethod.roles);
}


/**
 * How resource paths are mapped to roles so they can 
 * be looked up by role later:
 *
 * _readAccessPaths_ = {
 *   roleName1: {
 *      path1: true,
 *      path2: true,
 *      path3: true
 *   },
 *   roleName2: {
 *      path1: true,
 *      path2: true,
 *      path3: true
 *   }
 * }
 *
 * In other words:
 * _readAccessPaths_[roleName1][path1] = true;
 * _readAccessPaths_[roleName1][path2] = true;
 * _readAccessPaths_[roleName1][path3] = true;
 * _readAccessPaths_[roleName2][path1] = true;
 * etc.
 *
 * Call this method this way:
 *   // allow access regardless of user roles:
 *   this.allowReadAccess("public");
 *   // or for specific roles:
 *   this.allowReadAccess("private", "Administrator", "System Administrator", "Root");
 * 
 */
p.allowReadAccess = function(resourcePath){
	if (!resourcePath){
		trace("ERROR! allowRead: no resource path was passed in. At a minimum us '/' to indicate root access.");
		return;
	}
	
	// Remove the trailing slash.
	if (resourcePath.lastIndexOf("/") ==  (resourcePath.length - 1)){
		resourcePath = resourcePath.substring(0, resourcePath.length - 1);
	}
	
	
	resourcePath = this._fullResourcePath_ + resourcePath; // createComponent insures the full resource path ends in a "/"
	
	if(arguments.length == 1){
		if (! this._readAccessPaths_._all_) this._readAccessPaths_._all_ = {};
		this._readAccessPaths_._all_[resourcePath] = true;
	}
	else {
		for (var i = 1; i < arguments.length; i++){
			var roleName = arguments[i];
			if (! this._readAccessPaths_[roleName]) this._readAccessPaths_[roleName] = {};
			this._readAccessPaths_[roleName][resourcePath] = true;
		}
	}
}

p.allowWriteAccess = function(resourcePath){

	//trace("RTCFComponent.allowWriteAccess> resourcePath: " + resourcePath);

	if (!resourcePath){
		trace("ERROR! allowWrite: no resource path was passed in. At a minimum us '/' to indicate root access.");
		return;
	}
	
	resourcePath = this._fullResourcePath_ + resourcePath; // createComponent insures the full resource path ends in a "/"
	
	//trace("RTCFComponent.allowWriteAccess> resourcePath: " + resourcePath);
	
	if(arguments.length == 1){
		if (! this._writeAccessPaths_._all_) this._writeAccessPaths_._all_ = {};
		this._writeAccessPaths_._all_[resourcePath] = true;		
		//trace(this._writeAccessPaths_._all_[resourcePath] + ", " + resourcePath);		
	}
	else {
		for (var i = 1; i < arguments.length; i++){
			var roleName = arguments[i];
			if (! this._writeAccessPaths_[roleName]) this._writeAccessPaths_[roleName] = {};
			this._writeAccessPaths_[roleName][resourcePath] = true;
		}
	}
}


p.getSharedObject = function(name, persistence, netConnection){
	if (! this._resourcePath_){
		trace("ERROR! RTCFComponent.getSharedObject. Cannot get a shared object without a resource path." );
		return null;	
	}
	name = this._fullResourcePath_ + name;
	//trace("GETTING shared object named: " + name);
	return SharedObject.get(name, persistence, netConnection);
}

p.getStream = function(name){
	if (! this._resourcePath_){
		trace("ERROR! RTCFComponent.getStream. Cannot get a Stream object without a resource path." );
		return null;	
	}
	name = this._fullResourcePath_ + name;
	return Stream.get(name);
}

p.callClientRTCFComponent = function(client, methodName, responder, p1, p2){

	if (! this._rmiID_){
		trace("ERROR! RTCFComponent.callClientRTCFComponent. Cannot call a client method if the component's id is null." );
		return null;
	}
	
	var args = ["s2c", responder, this._rmiID_ , methodName];
	for(var i = 3; i < arguments.length; i++){
		args.push(arguments[i]);
	}
	
	//trace("arguments for client.call: " + args);
	
	if (client){
		return client.call.apply(client, args);
	}
	else {
		trace("ERROR! RTCFComponent.callClientRTCFComponent. client parameter missing or null: " + methodName);
		return null;
	}

}

/***** How to use this RTCFComponent class as a base class in JavaScript 1.5: 

try { var dummy = PeopleList; } catch ( e ) {

function PeopleList(id, classPath, resourcePath){
}

PeopleList.prototype = new RTCFComponent();

} // end catch


*****/


} // end catch